(function (win) {
//	1,获取当前的query,params,path，name，meta
//	2,当path为/的时候,指向的是首页
//	3,当path为*的时候,显示没有匹配项的时候指向的路径
//重定向
//replace
//go前进后退历史记录
//添加路由进入，离开生命周期


//尚未考虑嵌套路由,
//:pageid

Function.prototype.before = function (beforeFn) {
	var _self = this;	
	return function () {
		beforeFn.apply(this,arguments); 
		return _self.apply(this,arguments);
	}
}
Function.prototype.after = function (afterFn) {
	var _self = this;
	return function () {
		let res = _self.apply(this,arguments);
		afterFn.apply(this,arguments);
		return res;
	}
}

//var a = function () {
//	console.log(2);
//}
//function b () {
//	console.log(1)
//}
//function c () {
//	console.log(3);
//}
//var d = a.before(b).after(c)
//
//d()


	function Router (options) {
		const _default = {
			model:'hash',
			routes:null
		},
		_this = this;
		this.routes = {};
		this.one = 1;
		const _tempData = Object.assign({},_default,options)
		this.model = _tempData.model;
		this.el = _tempData.el;
		const _routes = _tempData.routes;
//		此处耦合性太高，需改
		Chain.call(this);
		unit.each(_routes,function (item,index) {
			//软绑定  回去看下
			this.pathCheck(item.path);
			_this.routes[item.path] = item;
		}.bind(unit));
		this.init();
	}
	Router.prototype = {
		init:function (){
			unit.mixin(this,new Method());
			unit.mixin(this,new LifeCycle());
			unit.mixin(this,new Domload());
			unit.extend(this,new Chain());
			console.log(this);
			const arr = ['fillBridge','replace','go'];
			for (let i = 0,item;item = arr[i++];){
				this[item] = this[item].before(this.beforeRouteEnter).after(this.afterRouteLeave);
			}
			this.addEvent();
		},
		addEvent:function (){
			this.exec();
			window.addEventListener('hashchange',this.exec.bind(this),false);
			window.addEventListener('load',this.exec.bind(this),false);
		},
		exec:function (){
			const currentPath = location.hash.slice(1);
			this.currentRoute(currentPath);
		},
		currentRoute:function (path){
			if(this.one == 1){
				//首次加载
				this.one++;
				this.setIndex();
				return;
			}
			try{
				this.push(path);
			}catch(e){
				this.reload();
			}
		}
	};
	
	function Domload () {
		
	}
	Domload.prototype = {
		//高性能
		//模板解析，数据添加vue中的东东
		fill:function (components) {
			//todo:这里本来应该使用appendChild,这里components主要使用的文字，所以用的是innerHTML
			document.querySelector(this.el).innerHTML = components;
		}
	};
	
	function Method () {
//		todo:在这里还可以把res,path抽离出来
	}
	Method.prototype = {
		push:function (path) {
			//编程式导航	
			this.fillBridge(path);
		},
		setIndex:function (){
			this.fillBridge('/');
		},
		reload:function () {
		//匹配不到路径的时候,指向的路径
			this.fillBridge('*');
		},
		fillBridge:function (path) {
			this.$routes(path);
			const _path = unit.path(path);
			let current = this.routes[_path];
			if(current.redirect){
				current = this.routes[current.redirect];
			}
			window.location.hash = '#'+current.path;
			if(!current.component){console.error(current.path + '组件书写格式有误'); return};
			this.fill(current.component);
		},
		replace:function (path) {
			//替换当前路径
			const _path = unit.path(path);
			this.$routes(path);
			 let url = location.href.split('#')[0];
			window.location.replace(url+'#'+path);
		},
		go:function (num){
			this.$routes(path);
			window.history.go(num);
		},
		$routes:function (path) {
			const res = unit.parseUrl(location.href);
			var queryResult = unit.query(res.search) || '';
			const _path = unit.path(path); 
			//todo:当路由为:pageid的时候应该
			
			return {
				query:queryResult,
				path:res.hash.slice(1) || '',
				meta:this.routes[_path].meta || '',
				name:this.routes[_path].name || ''
			}
		}
	}
	
	function LifeCycle () {
		
	}
	LifeCycle.prototype = {
		//生命周期
		beforeRouteEnter:function () {
			//现在的问题是无法获取到from,to,next
//			暂时没考虑异步的情况

			console.log(location.hash.slice(1));
			console.log('路由进入前');
			
		},
		afterRouteLeave:function () {
//			console.log(location.hash);
			console.log('路由离开后');
		},
		beforeRouteUpdate:function () {
			console.log('数据更新的时候进入这个路由,需要介入mvvm框架');
			
		}
	};
	
	
	function Chain() {
	    this.successor = null;
	}
	Chain.prototype = {
		constructor:Chain,
	    setNext:function (successor) {
	        return this.successor = successor;
	    },
	    next:function () {
	        return this.successor && this.successor.request.call(this.successor);
	    }
	};
	
	
	win.Router = Router;
	
})(window);

















